package com.wfh.frp.handler;

import com.wfh.frp.coder.ProxMsgEncoder;
import com.wfh.frp.coder.ProxyMsgDecoder;
import com.wfh.frp.model.ProxyMsg;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.UUID;

/**
 * @Title: VisitorHandler
 * @Author wangfenghuan
 * @Package com.wfh.frp.handler
 * @Date 2025/10/8 10:16
 * @description: 访客端处理器
 */
@Slf4j
public class VisitorHandler extends SimpleChannelInboundHandler<ProxyMsg> {

    private final String serverHost;

    private final int serverPort;

    /**
     * 与代理服务端的连接
     */
    private volatile Channel proxyChannel;

    /**
     * 本地连接id
     */
    private volatile String loaclChannelId;

    public VisitorHandler(String serverHost, int serverPort) {

        this.serverHost = serverHost;
        this.serverPort = serverPort;
    }

    /**
     * 收到消息
     * @param channelHandlerContext
     * @param proxyMsg
     * @throws Exception
     */
    @Override
    protected void messageReceived(ChannelHandlerContext channelHandlerContext, ProxyMsg proxyMsg) throws Exception {
        byte type = proxyMsg.getType();

        // 处理心跳消息
        if (type == ProxyMsg.HEARTBEAT) {
            log.debug("Received heartbeat from server: {}", proxyChannel.id());
            return; // 心跳消息不需要进一步处理
        }

        // 收到来自代理服务端转发来的数据
        if (type == ProxyMsg.TRANSFER && proxyChannel != null && proxyChannel.isActive()){
            // 转发给访客
            channelHandlerContext.writeAndFlush(proxyMsg);
        }
    }

    /**
     * 通道断开
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        if (proxyChannel != null){
            ProxyMsg closeMsg = new ProxyMsg();
            closeMsg.setType(ProxyMsg.DISCONNECT);
            closeMsg.setChannelId(loaclChannelId);
            proxyChannel.writeAndFlush(closeMsg);
            proxyChannel.close();
        }
    }

    /**
     * 有通道连接
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
       // 生成唯一通道Id
        this.loaclChannelId = UUID.randomUUID().toString();
        // 连接代理服务端
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(ctx.channel().eventLoop())
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel serverChannel) throws Exception {
                        serverChannel.pipeline()
                                .addLast(new ProxyMsgDecoder())
                                .addLast(new ProxMsgEncoder())
                                .addLast(new ProxyToServerHandler(ctx.channel()));
                    }
                });
        ChannelFuture connect = bootstrap.connect(serverHost, serverPort);
        connect.addListener((ChannelFutureListener) c -> {
            if (c.isSuccess()){
                // 如果连接成功
                 proxyChannel = c.channel();
                 // 发送CONNECT请求
                ProxyMsg proxyMsg = new ProxyMsg();
                proxyMsg.setType(ProxyMsg.SERVICE_CONNECT);
                proxyMsg.setChannelId(loaclChannelId);
                proxyChannel.writeAndFlush(proxyMsg);
            }else {
                ctx.close();
            }
        });
    }

    /**
     * 提供给 ProxyToServerHandler 回调写数据
     * @param msg
     * @param ctx
     */
    public void writeFromServer(ProxyMsg msg, ChannelHandlerContext ctx){
        ctx.executor().execute(() -> {
            Channel ch = ctx.channel();
            if (ch.isActive()){
                ch.writeAndFlush(msg);
            }
        });
    }
}
